﻿using System;
using System.Collections.Generic;
using System.IO;
using MiscUtil.Conversion;
using MiscUtil.IO;

namespace DivaScript.FT
{
    /// <summary>
    /// Project DIVA FT script file.
    /// </summary>
    public class Script
    {
        /// <summary>
        /// Returns the number of parameters based on the input opcode.
        /// </summary>
        public static int GetParameterCount(Opcode opcode)
        {
            switch (opcode)
            {
                case Opcode.END: return 0;
                case Opcode.TIME: return 1;
                case Opcode.MIKU_MOVE: return 4;
                case Opcode.MIKU_ROT: return 2;
                case Opcode.MIKU_DISP: return 2;
                case Opcode.MIKU_SHADOW: return 2;
                case Opcode.TARGET: return 7;
                case Opcode.SET_MOTION: return 4;
                case Opcode.SET_PLAYDATA: return 2;
                case Opcode.EFFECT: return 6;
                case Opcode.FADEIN_FIELD: return 2;
                case Opcode.EFFECT_OFF: return 1;
                case Opcode.SET_CAMERA: return 6;
                case Opcode.DATA_CAMERA: return 2;
                case Opcode.CHANGE_FIELD: return 1;
                case Opcode.HIDE_FIELD: return 1;
                case Opcode.MOVE_FIELD: return 3;
                case Opcode.FADEOUT_FIELD: return 2;
                case Opcode.EYE_ANIM: return 3;
                case Opcode.MOUTH_ANIM: return 5;
                case Opcode.HAND_ANIM: return 5;
                case Opcode.LOOK_ANIM: return 4;
                case Opcode.EXPRESSION: return 4;
                case Opcode.LOOK_CAMERA: return 5;
                case Opcode.LYRIC: return 2;
                case Opcode.MUSIC_PLAY: return 0;
                case Opcode.MODE_SELECT: return 2;
                case Opcode.EDIT_MOTION: return 4;
                case Opcode.BAR_TIME_SET: return 2;
                case Opcode.SHADOWHEIGHT: return 2;
                case Opcode.EDIT_FACE: return 1;
                case Opcode.MOVE_CAMERA: return 21;
                case Opcode.PV_END: return 0;
                case Opcode.SHADOWPOS: return 3;
                case Opcode.EDIT_LYRIC: return 2;
                case Opcode.EDIT_TARGET: return 5;
                case Opcode.EDIT_MOUTH: return 1;
                case Opcode.SET_CHARA: return 1;
                case Opcode.EDIT_MOVE: return 7;
                case Opcode.EDIT_SHADOW: return 1;
                case Opcode.EDIT_EYELID: return 1;
                case Opcode.EDIT_EYE: return 2;
                case Opcode.EDIT_ITEM: return 1;
                case Opcode.EDIT_EFFECT: return 2;
                case Opcode.EDIT_DISP: return 1;
                case Opcode.EDIT_HAND_ANIM: return 2;
                case Opcode.AIM: return 3;
                case Opcode.HAND_ITEM: return 3;
                case Opcode.EDIT_BLUSH: return 1;
                case Opcode.NEAR_CLIP: return 2;
                case Opcode.CLOTH_WET: return 2;
                case Opcode.LIGHT_ROT: return 3;
                case Opcode.SCENE_FADE: return 6;
                case Opcode.TONE_TRANS: return 6;
                case Opcode.SATURATE: return 1;
                case Opcode.FADE_MODE: return 1;
                case Opcode.AUTO_BLINK: return 2;
                case Opcode.PARTS_DISP: return 3;
                case Opcode.TARGET_FLYING_TIME: return 1;
                case Opcode.CHARA_SIZE: return 2;
                case Opcode.CHARA_HEIGHT_ADJUST: return 2;
                case Opcode.ITEM_ANIM: return 4;
                case Opcode.CHARA_POS_ADJUST: return 4;
                case Opcode.SCENE_ROT: return 1;
                case Opcode.MOT_SMOOTH: return 2;
                case Opcode.PV_BRANCH_MODE: return 1;
                case Opcode.DATA_CAMERA_START: return 2;
                case Opcode.MOVIE_PLAY: return 1;
                case Opcode.MOVIE_DISP: return 1;
                case Opcode.WIND: return 3;
                case Opcode.OSAGE_STEP: return 3;
                case Opcode.OSAGE_MV_CCL: return 3;
                case Opcode.CHARA_COLOR: return 2;
                case Opcode.SE_EFFECT: return 1;
                case Opcode.EDIT_MOVE_XYZ: return 9;
                case Opcode.EDIT_EYELID_ANIM: return 3;
                case Opcode.EDIT_INSTRUMENT_ITEM: return 2;
                case Opcode.EDIT_MOTION_LOOP: return 4;
                case Opcode.EDIT_EXPRESSION: return 2;
                case Opcode.EDIT_EYE_ANIM: return 3;
                case Opcode.EDIT_MOUTH_ANIM: return 2;
                case Opcode.EDIT_CAMERA: return 24;
                case Opcode.EDIT_MODE_SELECT: return 1;
                case Opcode.PV_END_FADEOUT: return 2;
                case Opcode.TARGET_FLAG: return 1;
                case Opcode.ITEM_ANIM_ATTACH: return 3;
                case Opcode.SHADOW_RANGE: return 1;
                case Opcode.HAND_SCALE: return 3;
                case Opcode.LIGHT_POS: return 4;
                case Opcode.FACE_TYPE: return 1;
                case Opcode.SHADOW_CAST: return 2;
                case Opcode.EDIT_MOTION_F: return 6;
                case Opcode.FOG: return 3;
                case Opcode.BLOOM: return 2;
                case Opcode.COLOR_COLLE: return 3;
                case Opcode.DOF: return 3;
                case Opcode.CHARA_ALPHA: return 4;
                case Opcode.AOTO_CAP: return 1;
                case Opcode.MAN_CAP: return 1;
                case Opcode.TOON: return 3;
                case Opcode.SHIMMER: return 3;
                case Opcode.ITEM_ALPHA: return 4;
                case Opcode.MOVIE_CUT_CHG: return 2;
                case Opcode.CHARA_LIGHT: return 3;
                case Opcode.STAGE_LIGHT: return 3;
                case Opcode.AGEAGE_CTRL: return 8;
                case Opcode.PSE: return 2;
                default: break;
            }
            return -1;
        }

        /// <summary>
        /// Parses a binary FT formatted *.dsc file
        /// and returns a PvCommand list of all contained commands.
        /// </summary>
        internal static List<PvCommand> ParseFile(string filePath, bool isBigEndian)
        {
            if (!File.Exists(filePath))
                throw new FileNotFoundException();

            var commands = new List<PvCommand>();

            var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read) { Position = 0x04 };
            using (var br = isBigEndian ? new EndianBinaryReader(EndianBitConverter.Big, fs) : new EndianBinaryReader(EndianBitConverter.Little, fs))
            {
                int currTime = 0;
                Opcode opcode;
                do
                {
                    var currParam = new List<int>();
                    opcode = (Opcode)br.ReadUInt32();

                    if (!Enum.IsDefined(typeof(Opcode), opcode))
                    {
                        Console.WriteLine($"Breaking loop at position 0x{fs.Position:X2}, undefined opcode: 0x{((uint)opcode):X2}");
                        Console.WriteLine($"[ERROR] {fs.Name}");
                        Console.WriteLine($"[ERROR] {fs.Position}/{fs.Length} bytes parsed");
                        break;
                    }

                    int length = GetParameterCount(opcode);
                    if (length < 0)
                    {
                        Console.WriteLine($"Breaking loop at position 0x{fs.Position:X2}, invalid parameter count for opcode: 0x{((uint)opcode):X2} - {opcode}");
                        Console.WriteLine($"[ERROR] {fs.Name}");
                        Console.WriteLine($"[ERROR] {fs.Position}/{fs.Length} bytes parsed");
                        break;
                    }

                    for (int i = 0; i < length; i++)
                        currParam.Add(br.ReadInt32());

                    currTime = opcode == Opcode.TIME ? currParam[0] : currTime;

                    commands.Add(new PvCommand(currTime, opcode.ToString(), currParam));

                } while (fs.Position < fs.Length);
            }

            return commands;
        }

        /// <summary>
        /// 
        /// </summary>
        internal static void WriteToFile(string outputPath, List<PvCommand> commands, bool isBigEndian)
        {
            var fs = new FileStream(outputPath, FileMode.Create);
            using (var bw = isBigEndian ? new EndianBinaryWriter(EndianBitConverter.Big, fs) : new EndianBinaryWriter(EndianBitConverter.Little, fs))
            {
                bw.Write(0x14050921);

                foreach (var command in commands)
                {
                    Opcode opcode;
                    try
                    {
                        opcode = (Opcode)Enum.Parse(typeof(Opcode), command.Opcode);
                    }
                    catch (Exception)
                    {
                        continue;
                    }
                    if (!Enum.IsDefined(typeof(Opcode), opcode))
                        continue;

                    bw.Write((int)opcode);
                    for (int i = 0; i < GetParameterCount(opcode); i++)
                    {
                        if (i < command.Parameters.Count)
                        {
                            bw.Write(command.Parameters[i]);
                        }
                        else
                        {
                            bw.Write(0);
                        }
                    }
                }
            }
            fs.Dispose();
        }
    }
}

// LOAD:000000000072C270
//  dword_C686B50 = 0;
//  dword_C686B54 = 0;
//  dword_C686B58 = 0;
//  qword_C686B60 = "END";
//  dword_C686B68 = 1;
//  dword_C686B6C = 1;
//  dword_C686B70 = 1;
//  qword_C686B78 = "TIME";
//  dword_C686B80 = 2;
//  dword_C686B84 = 3;
//  dword_C686B88 = 4;
//  qword_C686B90 = "MIKU_MOVE";
//  dword_C686B98 = 3;
//  dword_C686B9C = 1;
//  dword_C686BA0 = 2;
//  qword_C686BA8 = "MIKU_ROT";
//  dword_C686BB0 = 4;
//  dword_C686BB4 = 1;
//  dword_C686BB8 = 2;
//  qword_C686BC0 = "MIKU_DISP";
//  dword_C686BC8 = 5;
//  dword_C686BCC = 1;
//  dword_C686BD0 = 2;
//  qword_C686BD8 = "MIKU_SHADOW";
//  dword_C686BE0 = 6;
//  dword_C686BE4 = 7;
//  dword_C686BE8 = 7;
//  qword_C686BF0 = "TARGET";
//  dword_C686BF8 = 7;
//  dword_C686BFC = 3;
//  dword_C686C00 = 4;
//  qword_C686C08 = "SET_MOTION";
//  dword_C686C10 = 8;
//  dword_C686C14 = 1;
//  dword_C686C18 = 2;
//  qword_C686C20 = "SET_PLAYDATA";
//  dword_C686C28 = 9;
//  dword_C686C2C = 5;
//  dword_C686C30 = 6;
//  qword_C686C38 = "EFFECT";
//  dword_C686C40 = 0xA;
//  dword_C686C44 = 2;
//  dword_C686C48 = 2;
//  qword_C686C50 = "FADEIN_FIELD";
//  dword_C686C58 = 0xB;
//  dword_C686C5C = 1;
//  dword_C686C60 = 1;
//  qword_C686C68 = "EFFECT_OFF";
//  dword_C686C70 = 0xC;
//  dword_C686C74 = 6;
//  dword_C686C78 = 6;
//  qword_C686C80 = "SET_CAMERA";
//  dword_C686C88 = 0xD;
//  dword_C686C8C = 2;
//  dword_C686C90 = 2;
//  qword_C686C98 = "DATA_CAMERA";
//  dword_C686CA0 = 0xE;
//  dword_C686CA4 = 1;
//  dword_C686CA8 = 1;
//  qword_C686CB0 = "CHANGE_FIELD";
//  dword_C686CB8 = 0xF;
//  dword_C686CBC = 1;
//  dword_C686CC0 = 1;
//  qword_C686CC8 = "HIDE_FIELD";
//  dword_C686CD0 = 0x10;
//  dword_C686CD4 = 3;
//  dword_C686CD8 = 3;
//  qword_C686CE0 = "MOVE_FIELD";
//  dword_C686CE8 = 0x11;
//  dword_C686CEC = 2;
//  dword_C686CF0 = 2;
//  qword_C686CF8 = "FADEOUT_FIELD";
//  dword_C686D00 = 0x12;
//  dword_C686D04 = 2;
//  dword_C686D08 = 3;
//  qword_C686D10 = "EYE_ANIM";
//  dword_C686D18 = 0x13;
//  dword_C686D1C = 3;
//  dword_C686D20 = 5;
//  qword_C686D28 = "MOUTH_ANIM";
//  dword_C686D30 = 0x14;
//  dword_C686D34 = 4;
//  dword_C686D38 = 5;
//  qword_C686D40 = "HAND_ANIM";
//  dword_C686D48 = 0x15;
//  dword_C686D4C = 3;
//  dword_C686D50 = 4;
//  qword_C686D58 = "LOOK_ANIM";
//  dword_C686D60 = 0x16;
//  dword_C686D64 = 3;
//  dword_C686D68 = 4;
//  qword_C686D70 = "EXPRESSION";
//  dword_C686D78 = 0x17;
//  dword_C686D7C = 4;
//  dword_C686D80 = 5;
//  qword_C686D88 = "LOOK_CAMERA";
//  dword_C686D90 = 0x18;
//  dword_C686D94 = 1;
//  dword_C686D98 = 2;
//  qword_C686DA0 = "LYRIC";
//  dword_C686DA8 = 0x19;
//  dword_C686DAC = 0;
//  dword_C686DB0 = 0;
//  qword_C686DB8 = "MUSIC_PLAY";
//  dword_C686DC0 = 0x1A;
//  dword_C686DC4 = 1;
//  dword_C686DC8 = 2;
//  qword_C686DD0 = "MODE_SELECT";
//  dword_C686DD8 = 0x1B;
//  dword_C686DDC = 2;
//  dword_C686DE0 = 4;
//  qword_C686DE8 = "EDIT_MOTION";
//  dword_C686DF0 = 0x1C;
//  dword_C686DF4 = 2;
//  dword_C686DF8 = 2;
//  qword_C686E00 = "BAR_TIME_SET";
//  dword_C686E08 = 0x1D;
//  dword_C686E0C = 1;
//  dword_C686E10 = 2;
//  qword_C686E18 = "SHADOWHEIGHT";
//  dword_C686E20 = 0x1E;
//  dword_C686E24 = 2;
//  dword_C686E28 = 1;
//  qword_C686E30 = "EDIT_FACE";
//  dword_C686E38 = 0x1F;
//  dword_C686E3C = 19;
//  dword_C686E40 = 21;
//  qword_C686E48 = "MOVE_CAMERA";
//  dword_C686E50 = 0x20;
//  dword_C686E54 = 0;
//  dword_C686E58 = 0;
//  qword_C686E60 = "PV_END";
//  dword_C686E68 = 0x21;
//  dword_C686E6C = 2;
//  dword_C686E70 = 3;
//  qword_C686E78 = "SHADOWPOS";
//  dword_C686E80 = 0x22;
//  dword_C686E84 = 2;
//  dword_C686E88 = 2;
//  qword_C686E90 = "EDIT_LYRIC";
//  dword_C686E98 = 0x23;
//  dword_C686E9C = 5;
//  dword_C686EA0 = 5;
//  qword_C686EA8 = "EDIT_TARGET";
//  dword_C686EB0 = 0x24;
//  dword_C686EB4 = 1;
//  dword_C686EB8 = 1;
//  qword_C686EC0 = "EDIT_MOUTH";
//  dword_C686EC8 = 0x25;
//  dword_C686ECC = 1;
//  dword_C686ED0 = 1;
//  qword_C686ED8 = "SET_CHARA";
//  dword_C686EE0 = 0x26;
//  dword_C686EE4 = 7;
//  dword_C686EE8 = 7;
//  qword_C686EF0 = "EDIT_MOVE";
//  dword_C686EF8 = 0x27;
//  dword_C686EFC = 1;
//  dword_C686F00 = 1;
//  qword_C686F08 = "EDIT_SHADOW";
//  dword_C686F10 = 0x28;
//  dword_C686F14 = 1;
//  dword_C686F18 = 1;
//  qword_C686F20 = "EDIT_EYELID";
//  dword_C686F28 = 0x29;
//  dword_C686F2C = 2;
//  dword_C686F30 = 2;
//  qword_C686F38 = "EDIT_EYE";
//  dword_C686F40 = 0x2A;
//  dword_C686F44 = 1;
//  dword_C686F48 = 1;
//  qword_C686F50 = "EDIT_ITEM";
//  dword_C686F58 = 0x2B;
//  dword_C686F5C = 2;
//  dword_C686F60 = 2;
//  qword_C686F68 = "EDIT_EFFECT";
//  dword_C686F70 = 0x2C;
//  dword_C686F74 = 1;
//  dword_C686F78 = 1;
//  qword_C686F80 = "EDIT_DISP";
//  dword_C686F88 = 0x2D;
//  dword_C686F8C = 2;
//  dword_C686F90 = 2;
//  qword_C686F98 = "EDIT_HAND_ANIM";
//  dword_C686FA0 = 0x2E;
//  dword_C686FA4 = 3;
//  dword_C686FA8 = 3;
//  qword_C686FB0 = "AIM";
//  dword_C686FB8 = 0x2F;
//  dword_C686FBC = 3;
//  dword_C686FC0 = 3;
//  qword_C686FC8 = "HAND_ITEM";
//  dword_C686FD0 = 0x30;
//  dword_C686FD4 = 1;
//  dword_C686FD8 = 1;
//  qword_C686FE0 = "EDIT_BLUSH";
//  dword_C686FE8 = 0x31;
//  dword_C686FEC = 2;
//  dword_C686FF0 = 2;
//  qword_C686FF8 = "NEAR_CLIP";
//  dword_C687000 = 0x32;
//  dword_C687004 = 1;
//  dword_C687008 = 2;
//  qword_C687010 = "CLOTH_WET";
//  dword_C687018 = 0x33;
//  dword_C68701C = 3;
//  dword_C687020 = 3;
//  qword_C687028 = "LIGHT_ROT";
//  dword_C687030 = 0x34;
//  dword_C687034 = 6;
//  dword_C687038 = 6;
//  qword_C687040 = "SCENE_FADE";
//  dword_C687048 = 0x35;
//  dword_C68704C = 6;
//  dword_C687050 = 6;
//  qword_C687058 = "TONE_TRANS";
//  dword_C687060 = 0x36;
//  dword_C687064 = 1;
//  dword_C687068 = 1;
//  qword_C687070 = "SATURATE";
//  dword_C687078 = 0x37;
//  dword_C68707C = 1;
//  dword_C687080 = 1;
//  qword_C687088 = "FADE_MODE";
//  dword_C687090 = 0x38;
//  dword_C687094 = 2;
//  dword_C687098 = 2;
//  qword_C6870A0 = "AUTO_BLINK";
//  dword_C6870A8 = 0x39;
//  dword_C6870AC = 3;
//  dword_C6870B0 = 3;
//  qword_C6870B8 = "PARTS_DISP";
//  dword_C6870C0 = 0x3A;
//  dword_C6870C4 = 1;
//  dword_C6870C8 = 1;
//  qword_C6870D0 = "TARGET_FLYING_TIME";
//  dword_C6870D8 = 0x3B;
//  dword_C6870DC = 2;
//  dword_C6870E0 = 2;
//  qword_C6870E8 = "CHARA_SIZE";
//  dword_C6870F0 = 0x3C;
//  dword_C6870F4 = 2;
//  dword_C6870F8 = 2;
//  qword_C687100 = "CHARA_HEIGHT_ADJUST";
//  dword_C687108 = 0x3D;
//  dword_C68710C = 4;
//  dword_C687110 = 4;
//  qword_C687118 = "ITEM_ANIM";
//  dword_C687120 = 0x3E;
//  dword_C687124 = 4;
//  dword_C687128 = 4;
//  qword_C687130 = "CHARA_POS_ADJUST";
//  dword_C687138 = 0x3F;
//  dword_C68713C = 1;
//  dword_C687140 = 1;
//  qword_C687148 = "SCENE_ROT";
//  dword_C687150 = 0x40;
//  dword_C687154 = 2;
//  dword_C687158 = 2;
//  qword_C687160 = "MOT_SMOOTH";
//  dword_C687168 = 0x41;
//  dword_C68716C = 1;
//  dword_C687170 = 1;
//  qword_C687178 = "PV_BRANCH_MODE";
//  dword_C687180 = 0x42;
//  dword_C687184 = 2;
//  dword_C687188 = 2;
//  qword_C687190 = "DATA_CAMERA_START";
//  dword_C687198 = 0x43;
//  dword_C68719C = 1;
//  dword_C6871A0 = 1;
//  qword_C6871A8 = "MOVIE_PLAY";
//  dword_C6871B0 = 0x44;
//  dword_C6871B4 = 1;
//  dword_C6871B8 = 1;
//  qword_C6871C0 = "MOVIE_DISP";
//  dword_C6871C8 = 0x45;
//  dword_C6871CC = 3;
//  dword_C6871D0 = 3;
//  qword_C6871D8 = "WIND";
//  dword_C6871E0 = 0x46;
//  dword_C6871E4 = 3;
//  dword_C6871E8 = 3;
//  qword_C6871F0 = "OSAGE_STEP";
//  dword_C6871F8 = 0x47;
//  dword_C6871FC = 3;
//  dword_C687200 = 3;
//  qword_C687208 = "OSAGE_MV_CCL";
//  dword_C687210 = 0x48;
//  dword_C687214 = 2;
//  dword_C687218 = 2;
//  qword_C687220 = "CHARA_COLOR";
//  dword_C687228 = 0x49;
//  dword_C68722C = 1;
//  dword_C687230 = 1;
//  qword_C687238 = "SE_EFFECT";
//  dword_C687240 = 0x4A;
//  dword_C687244 = 9;
//  dword_C687248 = 9;
//  qword_C687250 = "EDIT_MOVE_XYZ";
//  dword_C687258 = 0x4B;
//  dword_C68725C = 3;
//  dword_C687260 = 3;
//  qword_C687268 = "EDIT_EYELID_ANIM";
//  dword_C687270 = 0x4C;
//  dword_C687274 = 2;
//  dword_C687278 = 2;
//  qword_C687280 = "EDIT_INSTRUMENT_ITEM";
//  dword_C687288 = 0x4D;
//  dword_C68728C = 4;
//  dword_C687290 = 4;
//  qword_C687298 = "EDIT_MOTION_LOOP";
//  dword_C6872A0 = 0x4E;
//  dword_C6872A4 = 2;
//  dword_C6872A8 = 2;
//  qword_C6872B0 = "EDIT_EXPRESSION";
//  dword_C6872B8 = 0x4F;
//  dword_C6872BC = 3;
//  dword_C6872C0 = 3;
//  qword_C6872C8 = "EDIT_EYE_ANIM";
//  dword_C6872D0 = 0x50;
//  dword_C6872D4 = 2;
//  dword_C6872D8 = 2;
//  qword_C6872E0 = "EDIT_MOUTH_ANIM";
//  dword_C6872E8 = 0x51;
//  dword_C6872EC = 24;
//  dword_C6872F0 = 24;
//  qword_C6872F8 = "EDIT_CAMERA";
//  dword_C687300 = 0x52;
//  dword_C687304 = 1;
//  dword_C687308 = 1;
//  qword_C687310 = "EDIT_MODE_SELECT";
//  dword_C687318 = 0x53;
//  dword_C68731C = 2;
//  dword_C687320 = 2;
//  qword_C687328 = "PV_END_FADEOUT";
//  dword_C687330 = 0x54;
//  dword_C687334 = 1;
//  dword_C687338 = 1;
//  qword_C687340 = "TARGET_FLAG";
//  dword_C687348 = 0x55;
//  dword_C68734C = 3;
//  dword_C687350 = 3;
//  qword_C687358 = "ITEM_ANIM_ATTACH";
//  dword_C687360 = 0x56;
//  dword_C687364 = 1;
//  dword_C687368 = 1;
//  qword_C687370 = "SHADOW_RANGE";
//  dword_C687378 = 0x57;
//  dword_C68737C = 3;
//  dword_C687380 = 3;
//  qword_C687388 = "HAND_SCALE";
//  dword_C687390 = 0x58;
//  dword_C687394 = 4;
//  dword_C687398 = 4;
//  qword_C6873A0 = "LIGHT_POS";
//  dword_C6873A8 = 0x59;
//  dword_C6873AC = 1;
//  dword_C6873B0 = 1;
//  qword_C6873B8 = "FACE_TYPE";
//  dword_C6873C0 = 0x5A;
//  dword_C6873C4 = 2;
//  dword_C6873C8 = 2;
//  qword_C6873D0 = "SHADOW_CAST";
//  dword_C6873D8 = 0x5B;
//  dword_C6873DC = 6;
//  dword_C6873E0 = 6;
//  qword_C6873E8 = "EDIT_MOTION_F";
//  dword_C6873F0 = 0x5C;
//  dword_C6873F4 = 3;
//  dword_C6873F8 = 3;
//  qword_C687400 = "FOG";
//  dword_C687408 = 0x5D;
//  dword_C68740C = 2;
//  dword_C687410 = 2;
//  qword_C687418 = "BLOOM";
//  dword_C687420 = 0x5E;
//  dword_C687424 = 3;
//  dword_C687428 = 3;
//  qword_C687430 = "COLOR_COLLE";
//  dword_C687438 = 0x5F;
//  dword_C68743C = 3;
//  dword_C687440 = 3;
//  qword_C687448 = "DOF";
//  dword_C687450 = 0x60;
//  dword_C687454 = 4;
//  dword_C687458 = 4;
//  qword_C687460 = "CHARA_ALPHA";
//  dword_C687468 = 0x61;
//  dword_C68746C = 1;
//  dword_C687470 = 1;
//  qword_C687478 = "AOTO_CAP";
//  dword_C687480 = 0x62;
//  dword_C687484 = 1;
//  dword_C687488 = 1;
//  qword_C687490 = "MAN_CAP";
//  dword_C687498 = 0x63;
//  dword_C68749C = 3;
//  dword_C6874A0 = 3;
//  qword_C6874A8 = "TOON";
//  dword_C6874B0 = 0x64;
//  dword_C6874B4 = 3;
//  dword_C6874B8 = 3;
//  qword_C6874C0 = "SHIMMER";
//  dword_C6874C8 = 0x65;
//  dword_C6874CC = 4;
//  dword_C6874D0 = 4;
//  qword_C6874D8 = "ITEM_ALPHA";
//  dword_C6874E0 = 0x66;
//  dword_C6874E4 = 2;
//  dword_C6874E8 = 2;
//  qword_C6874F0 = "MOVIE_CUT_CHG";
//  dword_C6874F8 = 0x67;
//  dword_C6874FC = 3;
//  dword_C687500 = 3;
//  qword_C687508 = "CHARA_LIGHT";
//  dword_C687510 = 0x68;
//  dword_C687514 = 3;
//  dword_C687518 = 3;
//  qword_C687520 = "STAGE_LIGHT";
//  dword_C687528 = 0x69;
//  dword_C68752C = 8;
//  dword_C687530 = 8;
//  qword_C687538 = "AGEAGE_CTRL";
//  dword_C687540 = 0x6A;
//  dword_C687544 = 2;
//  dword_C687548 = 2;
//  qword_C687550 = "PSE";